package com.tools.common.io;

import com.tools.common.object.Note;
import com.tools.common.object.string.VerifyKit;

import java.util.Objects;

/**
 * 主机与端口的映射包装类
 * */
@Note("主机与端口的映射包装类")
public final class HostNode {

    @Note("主机名")
    private final String host;

    @Note("端口")
    private final int port;

    /* **********************************************************************************
     *
     *          构造器
     *
     * *********************************************************************************
     * */

    public HostNode(String host, int port) {
        this.private_checkHostAndPort(host, port);
        this.host = host;
        this.port = port;
    }

    public HostNode(String hostAndPort) {
        if(VerifyKit.isHostAndPort(hostAndPort)) {
            int index = hostAndPort.lastIndexOf(":");
            this.host = hostAndPort.substring(0, index);
            this.port = Integer.parseInt(hostAndPort.substring(index + 1));
            this.private_checkHostAndPort(this.host, this.port);
            return;
        }
        throw new IllegalArgumentException(hostAndPort + " 不是标准的 【主机名:端口号】 的格式");
    }

    public static HostNode of(String host, int port) {
        return new HostNode(host, port);
    }

    public static HostNode of(String hostAndPort) {
        return new HostNode(hostAndPort);
    }

    /* **********************************************************************************
     *
     *          Getter / Setter
     *
     * *********************************************************************************
     * */

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    @Override
    public String toString() {
        return host + ':' + port;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;
        if(o instanceof HostNode) {
            HostNode that = (HostNode) o;
            return port == that.port && Objects.equals(host, that.host);
        }
        String s = o.toString();
        return Objects.equals(this.toString(), s);
    }

    @Override
    public int hashCode() {
        return this.toString().hashCode();
    }

    /* **********************************************************************************
     *
     *          公共方法
     *
     * *********************************************************************************
     * */

    @Note("提供给外部使用的校验方法")
    public static boolean checkHostAndPort(String host, int port) {
        return (host != null && !host.isEmpty()) && (port >= 0 && port <= 65535);
    }

    public static boolean checkHostAndPort(String hostAndPort) {
        if(!VerifyKit.isHostAndPort(hostAndPort)) return false;
        int index = hostAndPort.lastIndexOf(":");
        String host = hostAndPort.substring(0, index);
        int port = Integer.parseInt(hostAndPort.substring(index + 1));
        return !host.isEmpty() && port >= 0 && port <= 65535;
    }

    /* **********************************************************************************
     *
     *          私有逻辑
     *
     * *********************************************************************************
     * */

    @Note("校验端口和主机名是否符合要求，否则就抛出异常")
    private void private_checkHostAndPort(String host, int port) {
        if(host == null || host.isEmpty()) throw new IllegalArgumentException("主机名不能为空");
        if(port < 0 || port > 65535) throw new IllegalArgumentException("端口号必须在 0 ~ 65535 之间");
    }

}
